---
title: 이미지 서비스 API
i18nReady: true
---

import Since from '~/components/Since.astro';

`astro:assets`은 모든 이미지 최적화 서비스가 Astro 위에 서비스를 쉽게 구축할 수 있도록 설계되었습니다.

## 이미지 서비스란 무엇입니까?

Astro는 로컬과 외부라는 두 가지 유형의 이미지 서비스를 제공합니다.

- **로컬 서비스**는 정적 사이트의 빌드 시 또는 개발 모드와 요청 시 렌더링 모두에서 런타임 시 이미지 변환을 직접 처리합니다. 이는 Sharp, ImageMagick, Squoosh와 같은 라이브러리를 둘러싼 래퍼인 경우가 많습니다. 개발 모드와 요청 시 렌더링된 프로덕션 라우트에서 로컬 서비스는 API 엔드포인트를 사용하여 변환을 수행합니다.
- **외부 서비스**는 URL을 가리키며 Cloudinary, Vercel 또는 모든 [RIAPI](https://github.com/riapi/riapi) 호환 서버와 같은 서비스에 대한 지원을 추가할 수 있습니다.

## 이미지 서비스 API를 사용하여 빌드

서비스 정의는 다양한 필수 방법 ("후크")을 사용하여 내보낸 기본 객체의 형태를 취합니다.

외부 서비스는 출력 `<img>` 태그의 `src`를 가리키는 `getURL()`을 제공합니다.

로컬 서비스는 이미지 변환을 수행하는 `transform()` 메서드와 개발 모드 및 요청 시 렌더링용 엔드포인트를 사용하는 `getURL()` 및 `parseURL()` 메서드를 제공합니다.

두 유형의 서비스 모두 `getHTMLAttributes()`를 제공하여 출력 `<img>`의 다른 속성을 결정하고 `validateOptions()`를 제공하여 전달된 옵션을 검증하고 강화할 수 있습니다.

### 외부 서비스

외부 서비스는 최종 `<img>` 태그의 `src` 속성으로 사용될 원격 URL을 가리킵니다. 이 원격 URL은 이미지 다운로드, 변환 및 반환을 담당합니다.

```ts
import type { ExternalImageService, ImageTransform, AstroConfig } from "astro";

const service: ExternalImageService = {
  validateOptions(options: ImageTransform, imageConfig: AstroConfig['image']) {
    const serviceConfig = imageConfig.service.config;

    // 사용자가 설정한 최대 너비를 적용합니다.
    if (options.width && options.width > serviceConfig.maxWidth) {
      console.warn(`Image width ${options.width} exceeds max width ${serviceConfig.maxWidth}. Falling back to max width.`);
      options.width = serviceConfig.maxWidth;
    }

    return options;
  },
  getURL(options, imageConfig) {
    return `https://mysupercdn.com/${options.src}?q=${options.quality}&w=${options.width}&h=${options.height}`;
  },
  getHTMLAttributes(options, imageConfig) {
    const { src, format, quality, ...attributes } = options;
		return {
			...attributes,
			loading: options.loading ?? 'lazy',
			decoding: options.decoding ?? 'async',
		};
	}
};


export default service;
```

### 로컬 서비스

자신만의 로컬 서비스를 생성하려면 [내장된 엔드포인트](https://github.com/withastro/astro/blob/main/packages/astro/src/assets/endpoint/generic.ts) (`/_image`)를 가리키거나 서비스의 메서드를 호출할 수 있는 자체 엔드포인트를 추가로 생성할 수 있습니다.

```ts
import type { ImageTransform, LocalImageService, AstroConfig } from "astro";

const service: LocalImageService<AstroConfig["image"]> = {
  getURL(options: ImageTransform, imageConfig) {
    const searchParams = new URLSearchParams();
		searchParams.append('href', typeof options.src === "string" ? options.src : options.src.src);
		options.width && searchParams.append('w', options.width.toString());
		options.height && searchParams.append('h', options.height.toString());
		options.quality && searchParams.append('q', options.quality.toString());
		options.format && searchParams.append('f', options.format);
    return `/my_custom_endpoint_that_transforms_images?${searchParams}`;
    // 또는 내장된 엔드포인트를 사용하여 parsURL 및 변환 함수를 호출합니다.
    // 이 함수는 `/_image?${searchParams}`를 반환합니다.
  },
  parseURL(url: URL, imageConfig) {
    const params = url.searchParams;
    return {
      src: params.get('href')!,
      width: params.has('w') ? parseInt(params.get('w')!) : undefined,
      height: params.has('h') ? parseInt(params.get('h')!) : undefined,
			format: params.get('f'),
      quality: params.get('q'),
    };
  },
  async transform(inputBuffer: Uint8Array, options: { src: string, [key: string]: any }, imageConfig) {
    const { buffer } = await mySuperLibraryThatEncodesImages(options);
    return {
      data: buffer,
      format: options.format,
    };
  },
  getHTMLAttributes(options, imageConfig) {
		let targetWidth = options.width;
		let targetHeight = options.height;
		if (typeof options.src === "object") {
			const aspectRatio = options.src.width / options.src.height;

			if (targetHeight && !targetWidth) {
				targetWidth = Math.round(targetHeight * aspectRatio);
			} else if (targetWidth && !targetHeight) {
				targetHeight = Math.round(targetWidth / aspectRatio);
			}
		}

		const { src, width, height, format, quality, ...attributes } = options;

		return {
			...attributes,
			width: targetWidth,
			height: targetHeight,
			loading: attributes.loading ?? 'lazy',
			decoding: attributes.decoding ?? 'async',
		};
	},
	propertiesToHash: ['src', 'width', 'height', 'format', 'quality'],
};
export default service;
```

정적 사이트와 사전 렌더링된 경로 빌드 시 `<Image />` 및 `getImage(options)`는 모두 `transform()` 함수를 호출합니다. 각각 컴포넌트의 속성이나 `options` 인수를 통해 옵션을 전달합니다. 변환된 이미지는 `dist/_astro` 폴더에 빌드됩니다. 파일 이름에는 `propertiesToHash`에 전달된 속성의 해시가 포함됩니다. 이 속성은 선택 사항이며 기본값은 `['src', 'width', 'height', 'format', 'quality']`입니다. 사용자 정의 이미지 서비스에 생성된 이미지를 변경하는 추가 옵션이 있는 경우 배열에 추가합니다.

개발 모드와 요청 시 렌더링을 위해 어댑터를 사용할 때, Astro는 어떤 이미지를 최적화해야 하는지 미리 알 수 없습니다. Astro는 GET 엔드포인트 (기본적으로 `/_image`)를 사용하여 런타임에 이미지를 처리합니다. `<Image />` 및 `getImage()`는 해당 옵션을 `getURL()`에 전달하여 엔드포인트 URL을 반환합니다. 그런 다음 엔드포인트는 `parseURL()`을 호출하고 결과 속성을 `transform()`에 전달합니다.

#### getConfiguredImageService & imageConfig

자체 엔드포인트를 Astro 엔드포인트로 구현하는 경우 `getConfiguredImageService` 및 `imageConfig`를 사용하여 서비스의 `parseURL` 및 `transform` 메서드를 호출하고 이미지 구성을 제공할 수 있습니다.

이미지 서비스 구성 ([`image.service.config`](/ko/reference/configuration-reference/#imageservice))에 액세스하려면 `imageConfig.service.config`를 사용할 수 있습니다.

```ts title="src/api/my_custom_endpoint_that_transforms_images.ts"
import type { APIRoute } from "astro";
import { getConfiguredImageService, imageConfig } from 'astro:assets';

export const GET: APIRoute = async ({ request }) => {
  const imageService = await getConfiguredImageService();

  const imageTransform = imageService.parseURL(new URL(request.url), imageConfig);
  // ... imageTransform.src에서 이미지를 가져와 inputBuffer에 저장합니다.
  const { data, format } = await imageService.transform(inputBuffer, imageTransform, imageConfig);
  return new Response(data, {
			status: 200,
			headers: {
				'Content-Type': mime.getType(format) || ''
      }
    }
  );
}
```

전체 예시는 [내장 엔드포인트](https://github.com/withastro/astro/blob/main/packages/astro/src/assets/endpoint/generic.ts)를 참조하세요.

## 후크

### `getURL()`

<p>

**타입:** `(options: ImageTransform, imageConfig: AstroConfig['image']) => string | Promise<string>`<br />
<Since v="2.1.0" />
</p>

**로컬 및 외부 서비스에 필요함**

로컬 서비스의 경우 이 후크는 이미지를 생성하는 엔드포인트의 URL을 반환합니다 (요청 시 렌더링 및 개발 모드에서). 빌드 중에는 사용되지 않습니다. `getURL()`이 가리키는 로컬 엔드포인트는 `parseURL()`과 `transform()`을 모두 호출할 수 있습니다.

외부 서비스의 경우 이 후크는 이미지의 최종 URL을 반환합니다.

두 서비스 유형 모두 `options`는 사용자가 `<Image />` 컴포넌트의 속성 또는 `getImage()`에 대한 옵션으로 전달한 속성입니다. 그들은 다음과 같은 타입입니다:

```ts
export type ImageTransform = {
  // 이미지를 가져오는 ESM | 원격/public 이미지 경로
  src: ImageMetadata | string;
  width?: number | undefined;
  height?: number | undefined;
  widths?: number[] | undefined;
  densities?: (number | `${number}x`)[] | undefined;
  quality?: ImageQuality  | undefined;
  format?: OutputFormat | undefined;
  fit?: ImageFit | undefined;
  position?: string | undefined;
  [key: string]: any;
};
```

### `parseURL()`

<p>

**타입:** `(url: URL, imageConfig: AstroConfig['image']) => { src: string, [key: string]: any } | undefined | Promise<{ src: string, [key: string]: any }> | Promise<undefined>`<br />
<Since v="2.1.0" />
</p>

**로컬 서비스에만 필요합니다. 외부 서비스에 사용할 수 없음**

이 후크는 `getURL()`에 의해 생성된 URL을 `transform` (요청 시 렌더링 및 개발 모드에서)에 사용되는 다른 속성을 가진 객체로 다시 구문 분석합니다. 빌드 중에는 사용되지 않습니다.

### `transform()`

<p>

**타입:** `(inputBuffer: Uint8Array, options: { src: string, [key: string]: any }, imageConfig: AstroConfig['image']) => Promise<{ data: Uint8Array; format: ImageOutputFormat }>`<br />
<Since v="2.1.0" />
</p>

**로컬 서비스에만 필요합니다. 외부 서비스에 사용할 수 없음**

이 후크는 이미지를 변환하고 반환하며 빌드 중에 호출되어 최종 자산 파일을 생성합니다.

요청 시 렌더링 및 개발 모드에서 사용자에게 적절한 MIME 유형이 제공되도록 하려면 `format`을 반환해야 합니다.

### `getHTMLAttributes()`

<p>

**타입:** `(options: ImageTransform, imageConfig: AstroConfig['image'] ) => Record<string, any> | Promise<Record<string, any>>`<br />
<Since v="2.1.0" />
</p>

**로컬 및 외부 서비스 모두 선택 사항**

이 후크는 사용자가 전달한 매개변수 (`options`)를 기반으로 이미지를 HTML로 렌더링하는 데 사용되는 모든 추가 속성을 반환합니다.

### `getSrcSet()`

<p>

**타입:** `(options: ImageTransform, imageConfig: AstroConfig['image'] ) => UnresolvedSrcSetValue[] | Promise<UnresolvedSrcSetValue[]>`<br />
<Since v="3.3.0" />
</p>

**로컬 및 외부 서비스 모두 선택 사항입니다.**

이 후크는 `<img>` 또는 `<picture>`의 `source`에 `srcset` 속성을 생성하기 위해 지정된 이미지의 여러 변형을 생성합니다.

이 후크는 다음 속성을 가진 객체 배열을 반환합니다.

```ts
export type UnresolvedSrcSetValue = {
	transform: ImageTransform;
	descriptor?: string;
	attributes?: Record<string, any>;
};
```

### `validateOptions()`

<p>

**타입:** `(options: ImageTransform, imageConfig: AstroConfig['image'] ) => ImageTransform | Promise<ImageTransform>`
<Since v="2.1.4" />
</p>

**로컬 및 외부 서비스 모두 선택 사항**

이 후크를 사용하면 사용자가 전달한 옵션을 검증하고 강화할 수 있습니다. 이는 기본 옵션을 설정하거나 사용자에게 매개변수가 필요함을 알리는 데 유용합니다.

[Astro 내장 서비스에서 `validateOptions()`가 어떻게 사용되는지 확인하세요.](https://github.com/withastro/astro/blob/0ab6bad7dffd413c975ab00e545f8bc150f6a92f/packages/astro/src/assets/services/service.ts#L124)

## 사용자 구성

`astro.config.mjs` 파일에서 사용할 이미지 서비스를 구성합니다. 구성은 다음 형식을 취합니다.

```js title="astro.config.mjs"
import { defineConfig } from "astro/config";

export default defineConfig({
  image: {
    service: {
      entrypoint: "your-entrypoint", // 'astro/assets/services/sharp' | string,
      config: {
        // ... 서비스별 구성. 선택적.
      }
    }
  },
});
```

## 유틸리티

Astro는 사용자 정의 이미지 서비스를 개발하는 데 사용할 수 있는 여러 도우미 함수를 제공합니다. 이러한 유틸리티는 `astro/assets/utils`에서 가져올 수 있습니다.

```ts
import { 
    isRemoteAllowed,
    matchHostname,
    matchPathname,
    matchPattern,
    matchPort,
    matchProtocol,
    isESMImportedImage,
    isRemoteImage,
    resolveSrc,
    imageMetadata,
    emitESMImage,
    emitImageMetadata,
    getOrigQueryParams,
    inferRemoteSize,
    propsToFilename,
    hashTransform
} from "astro/assets/utils";
```

### `isRemoteAllowed()`

<p>
**타입:** `(src: string, { domains, remotePatterns }: { domains: string[], remotePatterns: RemotePattern[] }) => boolean`<br />
<Since v="4.0.0" />
</p>

제공된 도메인 및 원격 패턴을 기반으로, 소스 URL로 식별되는 지정된 원격 리소스가 허용되는지 여부를 결정합니다.

```ts
import { isRemoteAllowed } from 'astro/assets/utils';

const testImageURL = 'https://example.com/images/test.jpg';
const domains = ['example.com', 'anotherdomain.com'];
const remotePatterns = [
  { protocol: 'https', hostname: 'images.example.com', pathname: '/**' }, // 이 호스트 이름 아래의 모든 경로를 허용합니다.
];

const url = new URL(testImageURL);
const isAllowed = isRemoteAllowed(url.href, { domains, remotePatterns });

console.log(`Is the remote image allowed? ${isAllowed}`);
```

### `matchHostname()`

<p>
**타입:** `(url: URL, hostname?: string, allowWildcard = false) => boolean`<br />
<Since v="4.0.0" />
</p>

주어진 URL의 호스트 이름이 지정된 호스트 이름과 일치하는지 확인하며, 선택적으로 와일드카드 패턴을 지원합니다.

```ts
import { matchHostname } from 'astro/assets/utils';

const testURL = new URL('https://sub.example.com/path/to/resource');

// matchHostname의 사용 예시입니다.
const hostnameToMatch = 'example.com';

// 와일드카드 없이 비교합니다.
const isMatchWithoutWildcard = matchHostname(testURL, hostnameToMatch);
console.log(`Does the hostname match without wildcard? ${isMatchWithoutWildcard}`); // 출력: false

// 와일드카드를 사용하여 비교합니다.
const isMatchWithWildcard = matchHostname(testURL, hostnameToMatch, true);
console.log(`Does the hostname match with wildcard? ${isMatchWithWildcard}`); // 출력: true
```

### `matchPathname()`

<p>
**타입:** `(url: URL, pathname?: string, allowWildcard = false) => boolean`<br />
<Since v="4.0.0" />
</p>

주어진 URL의 경로 이름이 지정된 패턴과 일치하는지 확인하며, 선택적으로 와일드카드를 지원합니다.

```ts
import { matchPathname } from 'astro/assets/utils';

const testURL = new URL('https://example.com/images/photo.jpg');

// 경로 이름 일치 예시입니다.
const pathnameToMatch = '/images/photo.jpg';

// 와일드카드 없이 비교합니다.
const isMatchWithoutWildcard = matchPathname(testURL, pathnameToMatch);
console.log(`Does the pathname match without wildcard? ${isMatchWithoutWildcard}`); // 출력: true

// 와일드카드를 사용하여 비교합니다.
const wildcardPathname = '/images/*';
const isMatchWithWildcard = matchPathname(testURL, wildcardPathname, true);
console.log(`Does the pathname match with wildcard? ${isMatchWithWildcard}`); // 출력: true
```

### `matchPattern()`

<p>
**타입:** `(url: URL, remotePattern: RemotePattern) => boolean`<br />
<Since v="4.0.0" />
</p>

주어진 URL이 프로토콜, 호스트 이름, 포트 및 경로 이름을 기반으로 지정된 원격 패턴과 일치하는지 평가합니다.

```ts
import { matchPattern } from 'astro/assets/utils';

const testURL = new URL('https://images.example.com/photos/test.jpg');

// URL을 일치시키는 원격 패턴을 정의합니다.
const remotePattern = {
  protocol: 'https',
  hostname: 'images.example.com',
  pathname: '/photos/**', // `/photos/` 아래의 모든 파일을 허용하는 와일드카드입니다.
  port: '', // 선택 사항: 모든 포트와 일치시키거나 기본값으로 사용하기 위해 비워둡니다.
};

// URL이 원격 패턴과 일치하는지 확인합니다.
const isPatternMatched = matchPattern(testURL, remotePattern);

console.log(`Does the URL match the remote pattern? ${isPatternMatched}`); // 출력: true
```

### `matchPort()`

<p>
**타입:** `(url: URL, port?: string) => boolean`<br />
<Since v="4.0.0" />
</p>

주어진 URL의 포트가 지정된 포트와 일치하는지 확인합니다. 포트가 제공되지 않으면 `true`를 반환합니다.

```ts
import { matchPort } from 'astro/assets/utils';

const testURL1 = new URL('https://example.com:8080/resource');
const testURL2 = new URL('https://example.com/resource');

// matchPort의 사용 예시입니다.
const portToMatch = '8080';

// URL을 지정된 포트와 비교합니다.
const isPortMatch1 = matchPort(testURL1, portToMatch);
console.log(`Does the port match? ${isPortMatch1}`); // 출력: true

// 지정된 포트 없이 URL을 비교합니다. (기본 포트를 사용한다고 가정합니다.)
const isPortMatch2 = matchPort(testURL2, portToMatch);
console.log(`Does the port match? ${isPortMatch2}`); // 출력: false

// 명시적으로 제공된 포트 없이 URL을 확인합니다. (포트가 정의되지 않은 경우 기본적으로 true입니다.)
const isPortMatch3 = matchPort(testURL1);
console.log(`Does the port match (no port specified)? ${isPortMatch3}`); // 출력: true
```

### `matchProtocol()`

<p>
**타입:** `(url: URL, protocol?: string) => boolean`<br />
<Since v="4.0.0" />
</p>

제공된 URL의 프로토콜을 지정된 프로토콜과 비교합니다.

```ts
import { matchProtocol } from 'astro/assets/utils';

const testURL1 = new URL('https://example.com/resource');
const testURL2 = new URL('http://example.com/resource');

// matchProtocol의 사용 예시입니다.
const protocolToMatch = 'https';

// 정확한 프로토콜을 사용한 URL과 비교합니다.
const isProtocolMatch1 = matchProtocol(testURL1, protocolToMatch);
console.log(`Does the protocol match for testURL1? ${isProtocolMatch1}`); // 출력: true

// 정확하지 않은 프로토콜을 사용한 URL과 비교합니다.
const isProtocolMatch2 = matchProtocol(testURL2, protocolToMatch);
console.log(`Does the protocol match for testURL2? ${isProtocolMatch2}`); // 출력: false

// 명시적으로 제공된 프로토콜 없이 URL을 확인합니다. (프로토콜이 정의되지 않은 경우 기본적으로 true입니다.)
const isProtocolMatch3 = matchProtocol(testURL1);
console.log(`Does the protocol match (no protocol specified)? ${isProtocolMatch3}`); // 출력: true
```

### `isESMImportedImage()`

<p>
  **타입:** `(src: ImageMetadata | string) => boolean`<br />
  <Since v="4.0.0" />
</p>

주어진 소스가 ECMAScript 모듈 (ESM)로 가져온 이미지인지 판별합니다.

```ts
import { isESMImportedImage } from 'astro/assets/utils';

// isESMImportedImage의 예시 사용법
const imageMetadataExample = {
  src: '/images/photo.jpg',
  width: 800,
  height: 600,
  format: 'jpg',
};

const filePathExample = '/images/photo.jpg';

// 입력이 ESM으로 가져온 이미지인지 확인합니다.
const isMetadataImage = isESMImportedImage(imageMetadataExample);
console.log(`Is imageMetadataExample an ESM imported image? ${isMetadataImage}`); // 출력: true

const isFilePathImage = isESMImportedImage(filePathExample);
console.log(`Is filePathExample an ESM imported image? ${isFilePathImage}`); // 출력: false
```


### `isRemoteImage()`

<p>
  **타입:** `(src: ImageMetadata | string) => boolean`<br />
  <Since v="4.0.0" />
</p>

제공된 소스가 문자열 형태의 원격 이미지 URL인지 판별합니다.

```ts
import { isRemoteImage } from 'astro/assets/utils';

// isRemoteImage의 예시 사용법
const remoteImageUrl = 'https://example.com/images/photo.jpg';
const localImageMetadata = {
  src: '/images/photo.jpg',
  width: 800,
  height: 600,
  format: 'jpg',
};

// 입력이 원격 이미지 URL인지 확인합니다.
const isRemote1 = isRemoteImage(remoteImageUrl);
console.log(`Is remoteImageUrl a remote image? ${isRemote1}`); // 출력: true

const isRemote2 = isRemoteImage(localImageMetadata);
console.log(`Is localImageMetadata a remote image? ${isRemote2}`); // 출력: false
```

### `resolveSrc()`

<p>
  **타입:** `(src: UnresolvedImageTransform['src']) => Promise<string | ImageMetadata>`<br />
  <Since v="4.0.0" />
</p>

이미지 소스를 반환합니다. 이 함수는 `src`가 Promise (예: 동적 `import()`)인 경우, 이를 `await`하여 올바른 `src` 값을 추출합니다. `src`가 이미 해석된 값이면 그대로 반환합니다.

```ts
import { resolveSrc } from 'astro/assets/utils';
import localImage from "./images/photo.jpg";

const resolvedLocal = await resolveSrc(localImage);
// `{ src: '/images/photo.jpg', width: 800, height: 600, format: 'jpg' }`가 됩니다.

const resolvedRemote = await resolveSrc("https://example.com/remote-img.jpg");
// `"https://example.com/remote-img.jpg"`가 됩니다.

const resolvedDynamic = await resolveSrc(import("./images/dynamic-image.jpg"))
// `{ src: '/images/dynamic-image.jpg', width: 800, height: 600, format: 'jpg' }`가 됩니다.
```


### `imageMetadata()`

<p>
  **타입:** `(data: Uint8Array, src?: string) => Promise<Omit<ImageMetadata, 'src' | 'fsPath'>>`<br />
  <Since v="4.0.0" />
</p>

제공된 이미지 데이터에서 크기, 형식, 방향과 같은 이미지 메타데이터를 추출합니다.

```ts
import { imageMetadata } from 'astro/assets/utils';

async function extractImageMetadata() {
  // 예시 이미지 데이터 (Uint8Array)
  const exampleImageData = new Uint8Array([/* ...바이너리 이미지 데이터... */]);

  // 선택적인 소스 경로 (디버깅 또는 추가 메타데이터 컨텍스트에 유용합니다.)
  const sourcePath = '/images/photo.jpg';

  try {
    // 이미지 데이터에서 메타데이터를 추출합니다.
    const metadata = await imageMetadata(exampleImageData, sourcePath);

    console.log('Extracted Image Metadata:', metadata);
    // 예시 출력:
    // {
    //   width: 800,
    //   height: 600,
    //   format: 'jpg',
    //   orientation: undefined
    // }
  } catch (error) {
    console.error('Failed to extract metadata from image:', error);
  }
}

await extractImageMetadata();
```

### `emitESMImage()`

:::caution[더 이상 사용되지 않음]
대신 [`emitImageMetadata`](#emitimagemetadata) 함수를 사용하세요.
:::

<p>
  **타입:** `(id: string | undefined, _watchMode: boolean, experimentalSvgEnabled: boolean,  fileEmitter?: FileEmitter) => Promise<ImageMetadataWithContents | undefined>`<br />
  <Since v="4.0.0" />
</p>

이미지 파일을 처리하여 메타데이터를 추출하고, 선택적으로 파일의 콘텐츠를 추출합니다. 빌드 모드에서는 `fileEmitter`를 사용하여 자산 참조를 생성합니다. 개발 모드에서는 메타데이터를 포함한 쿼리 매개변수가 있는 로컬 파일 URL로 해석합니다.

```ts

import { emitESMImage } from 'astro/assets/utils';

const imageId = '/images/photo.jpg';
const unusedWatchMode = false; // 사용 중단, 미사용
const unusedExperimentalSvgEnabled = false; // SVG를 사용 중이고, 파일 데이터를 임베드하려는 경우에만 `true`로 설정합니다.

try {
  const result = await emitESMImage(imageId, unusedWatchMode, unusedExperimentalSvgEnabled);
  if (result) {
    console.log('Image metadata with contents:', result);
    // 예시 출력:
    // {
    //   width: 800,
    //   height: 600,
    //   format: 'jpg',
    //   contents: Uint8Array([...])
    // }
  } else {
    console.log('No metadata was emitted for this image.');
  }
} catch (error) {
  console.error('Failed to emit ESM image:', error);
}

```

### `emitImageMetadata()`

<p>
  **타입:** `(id: string | undefined, fileEmitter?: FileEmitter) => Promise<ImageMetadataWithContents | undefined>`<br />
  <Since v="5.7.0" />
</p>

이미지 파일을 처리하여 메타데이터를 내보내고 선택적으로 콘텐츠를 내보냅니다. 빌드 모드에서는 `fileEmitter`를 사용하여 자산 참조를 생성합니다. 개발 모드에서는 메타데이터를 위한 쿼리 매개변수가 있는 로컬 파일 URL로 해석됩니다.

```ts

import { emitImageMetadata } from 'astro/assets/utils';

const imageId = '/images/photo.jpg';

try {
  const result = await emitImageMetadata(imageId);
  if (result) {
    console.log('콘텐츠를 포함한 이미지 메타데이터:', result);
    // 예시 출력:
    // {
    //   width: 800,
    //   height: 600,
    //   format: 'jpg',
    //   contents: Uint8Array([...])
    // }
  } else {
    console.log('이 이미지에서 내보낸 메타데이터가 없습니다.');
  }
} catch (error) {
  console.error('ESM 이미지를 내보내는 데 실패했습니다:', error);
}

```

### `getOrigQueryParams()`

<p>
  **타입:** `(params: URLSearchParams) => Pick<ImageMetadata, 'width' | 'height' | 'format'> | undefined`<br />
  <Since v="4.0.0" />
</p>


[`URLSearchParams` 객체](https://developer.mozilla.org/ko/docs/Web/API/URLSearchParams)에서 이미지의 `width`, `height` 및 `format`을 검색합니다. 이러한 매개변수가 누락되었거나 유효하지 않으면 함수는 `undefined`를 반환합니다.

```ts

import { getOrigQueryParams } from 'astro/assets/utils';

const url = new URL('https://example.com/image.jpg?width=800&height=600&format=jpg');
const queryParams = url.searchParams;

// 원본 쿼리 매개변수를 추출합니다.
const origParams = getOrigQueryParams(queryParams);

if (origParams) {
  console.log('Original query parameters:', origParams);
  // 예시 출력:
  // {
  //   width: 800,
  //   height: 600,
  //   format: 'jpg'
  // }
} else {
  console.log('Failed to extract original query parameters.');
}
```

### `inferRemoteSize()`

<p>
  **타입:** `(url: string) => Promise<Omit<ImageMetadata, 'src' | 'fsPath'>>`<br />
  <Since v="4.0.0" />
</p>

데이터를 스트리밍하고 충분한 메타데이터를 사용할 수 있을 때까지 점진적으로 분석하여 원격 이미지의 크기를 추론합니다.

```ts

import { inferRemoteSize } from 'astro/assets/utils';

async function getRemoteImageSize() {
  const remoteImageUrl = 'https://example.com/image.jpg';

  try {
    // URL에서 원격 이미지 크기를 추론합니다.
    const imageSize = await inferRemoteSize(remoteImageUrl);

    console.log('Inferred remote image size:', imageSize);
    // 예시 출력:
    // {
    //   width: 1920,
    //   height: 1080,
    //   format: 'jpg'
    // }
  } catch (error) {
    console.error('Failed to infer the size of the remote image:', error);
  }
}

await getRemoteImageSize();
```

### `propsToFilename()`

<p>
  **타입:** `(filePath: string, transform: ImageTransform, hash: string) => string`<br />
  <Since v="4.0.0" />
</p>

소스 경로, 변환 속성 및 고유한 해시를 기반으로 이미지의 포맷팅된 파일 이름을 생성합니다.

포맷팅된 파일 이름은 다음 구조를 따릅니다.

`<prefixDirname>/<baseFilename>_<hash><outputExtension>`

- `prefixDirname`: 이미지가 ESM으로 가져온 이미지인 경우, 원본 파일 경로의 디렉토리 이름입니다. 그렇지 않으면 빈 문자열입니다.
- `baseFilename`: 파일이 `data:` URI인 경우 파일의 기본 이름 또는 해싱된 짧은 이름입니다.
- `hash`: 변환된 파일을 구별하기 위해 생성된 고유한 해시 문자열입니다.
- `outputExtension`: `transform.format` 또는 원본 파일 확장명에서 파생된 원하는 출력 파일 확장명입니다.

```ts
import { propsToFilename } from 'astro/assets/utils';

function generateTransformedFilename() {
  const filePath = '/images/photo.jpg';
  const transform = {
    format: 'png',
    src: '/images/photo.jpg'
  };
  const hash = 'abcd1234';

  // 파일 경로, 변환 및 해시를 기반으로 변환된 파일 이름을 생성합니다.
  const filename = propsToFilename(filePath, transform, hash);

  console.log('Generated transformed filename:', filename);
  // 예시 출력: '/images/photo_abcd1234.png'
}

generateTransformedFilename();
```

### `hashTransform()`

<p>
  **타입:** `(transform: ImageTransform, imageService: string, propertiesToHash: string[]) => string`<br />
  <Since v="4.0.0" />
</p>

제공된 `transform` 객체를 선택한 속성 및 지정된 `imageService`를 기반으로 해시 문자열로 변환합니다.

```ts

import { hashTransform } from 'astro/assets/utils';

function generateTransformHash() {
  const transform = {
    src: '/images/photo.jpg',
    width: 800,
    height: 600,
    format: 'jpg',
  };

  const imageService = 'astroImageService';
  const propertiesToHash = ['width', 'height', 'format'];

  // 변환, 이미지 서비스 및 속성을 기반으로 해시를 생성합니다.
  const hash = hashTransform(transform, imageService, propertiesToHash);

  console.log('Generated transform hash:', hash);
  // 예시 출력: 'd41d8cd98f00b204e9800998ecf8427e'
}

generateTransformHash();
```
